Premier bloc de code : importation des librairies.
library(dplyr)
library(ggplot2)
library(tidytext)
library(tm)
library(knitr)
library(SemNetCleaner)
data("stop_words")
custom_stop_words <- tibble(word = c("plot","wild","slug","manipulation","apple","significant","free","led"),
lexicon = c("custom"))
combined_stop_words <- bind_rows(stop_words, custom_stop_words) # didn't find the way to combine tibbles earlier, wich is why some code chunks work with the two "stop words" dictionnaries separetly.
Deuxième bloc de code : définition des variables.
#-----------------------------
earthworms <- read.csv("~/Documents/GitHub/EarthwormsMetanalysis/ExtractionBiblio/data_articles_metaanalyses.csv")
abstracts<-c()
#---------------------
names(earthworms)
## [1] "X" "MA" "Title" "First.author"
## [5] "Last.author" "Abstract" "OnResearchgate" "DOI"
## [9] "rg_URL"
n = nrow(earthworms)
Troisième bloc de code: ajout d’une colonne “aboutEarthworms”.
earthworms <- earthworms %>% mutate(aboutEarthworms = rep(TRUE,n))
Quatrième bloc de code: Construction de la liste des abstracts.
abstracts=earthworms$Abstract
Cinquième bloc de code : Construction d’un dataframe de tokens.
# Unnest tokens for the current abstract
unnested_tokens <- tibble(abstracts) %>%
unnest_tokens(word, abstracts)
# Append the unnested tokens to the list
unnested_tokens<-unnested_tokens%>%anti_join(stop_words)
unnested_tokens<-unnested_tokens %>% rowwise() %>% mutate(word = singularize(word))
Analyse du dataframe: trouver les mots les plus communs dans les quatre MA confondues.
ordre=unnested_tokens %>%
count(word, sort = TRUE) %>%
filter(n > 100) %>%
mutate(word = reorder(word, n,decreasing=TRUE))
ordre$word = factor(ordre$word,levels=rev(levels(ordre$word)))
ggplot(ordre,aes(n, word)) +
geom_col() +
labs(y = NULL)
On peut voir que les trois mots les plus fréquents dans les
articles des quatres métaanalyses confondues sont earthworm,
soil et plant. On peut donc penser que les
métaanalyses sont davantage portées sur le rôle écologique du ver de
terre que sur l’étude des vers de terre à part entière.
MA1: “Soil chemistry turned upside down: a meta-analysis of
invasive earthworm effects on soil chemical properties”
MA2:
“Earthworms affect plant growth and resistance against herbivores: A
meta-analysis”
MA3: “The unseen invaders: introduced earthworms as
drivers of change in plant communities in North American forests (a
meta-analysis)”
MA4: “Earthworms increase plant production: a
meta-analysis”
splitedData <- split(earthworms,earthworms$MA)
abstracts1<-c()
MA1 <- splitedData$MA1
nMA1 <- nrow(MA1)
abstracts1<-MA1$Abstract
unnested_tokens1 <- tibble(abstracts1) %>%
unnest_tokens(word, abstracts1)
unnested_tokens1<-unnested_tokens1 %>% anti_join(stop_words)
unnested_tokens1<-unnested_tokens1 %>% rowwise() %>% mutate(word = singularize(word))
abstracts2<-c()
MA2 <- splitedData$MA2
nMA2 <- nrow(MA2)
abstracts2<-MA2$Abstract
unnested_tokens2 <- tibble(abstracts2) %>%
unnest_tokens(word, abstracts2)
unnested_tokens2<-unnested_tokens2 %>% anti_join(stop_words)
unnested_tokens2<-unnested_tokens2 %>% rowwise() %>% mutate(word = singularize(word))
abstracts3<-c()
MA3 <- splitedData$MA3
nMA3 <- nrow(MA3)
abstracts3<-MA3$Abstract
unnested_tokens3 <- tibble(abstracts3) %>%
unnest_tokens(word, abstracts3)
unnested_tokens3<-unnested_tokens3 %>% anti_join(stop_words)
unnested_tokens3<-unnested_tokens3 %>% rowwise() %>% mutate(word = singularize(word))
abstracts4<-c()
MA4 <- splitedData$MA4
nMA4 <- nrow(MA4)
abstracts4<-MA4$Abstract
unnested_tokens4 <- tibble(abstracts4) %>%
unnest_tokens(word, abstracts4)
unnested_tokens4<-unnested_tokens4 %>% anti_join(stop_words)
unnested_tokens4<-unnested_tokens4 %>% rowwise() %>% mutate(word = singularize(word))
ordre1=unnested_tokens1 %>%
count(word, sort = TRUE) %>%
filter(n > 25) %>%
mutate(word = reorder(word, n,decreasing=TRUE))
ordre1$word = factor(ordre1$word,levels=rev(levels(ordre1$word)))
plot1<-ggplot(ordre1,aes(n, word)) +
geom_col() +
labs(y = NULL)
ordre2=unnested_tokens2 %>%
count(word, sort = TRUE) %>%
filter(n > 25) %>%
mutate(word = reorder(word, n,decreasing=TRUE))
ordre2$word = factor(ordre2$word,levels=rev(levels(ordre2$word)))
plot2<-ggplot(ordre2,aes(n, word)) +
geom_col() +
labs(y = NULL)
ordre3=unnested_tokens3 %>%
count(word, sort = TRUE) %>%
filter(n > 25) %>%
mutate(word = reorder(word, n,decreasing=TRUE))
ordre3$word = factor(ordre3$word,levels=rev(levels(ordre3$word)))
plot3<-ggplot(ordre3,aes(n, word)) +
geom_col() +
labs(y = NULL)
ordre4=unnested_tokens4 %>%
count(word, sort = TRUE) %>%
filter(n > 25) %>%
mutate(word = reorder(word, n,decreasing=TRUE))
ordre4$word = factor(ordre4$word,levels=rev(levels(ordre4$word)))
plot4<-ggplot(ordre4,aes(n, word)) +
geom_col() +
labs(y = NULL)
Quels sont les mots les plus communs dans chacunes des MA?
library(egg)
ggarrange(plot1,plot2,plot3,plot4,widths = c(5,5),labels = c("1","2","3","4"))
On remarque que les mots les plus fréquents dans les articles des
métaanalyses sont: - earthworm, soil et
forest pour la MA1 (qui semble donc s’intéresser plus
particulièrement à l’écosystème forestier). - plant,
earthworm et effect pour la MA2 (qui semble donc
vouloir étudier précisément les effets des vers de terre sur les
plantes). - earthworm, specie, et plant pour
la MA3 (qui semble donc s’intéresser plus particulièrement à certaines
espèces de vers de terre et leurs relations avec les plantes). -
earthworm, plant et soil pour la MA4 (qui
semble donc étudier l’influence des vers de terre sur les sols et les
plantes).
MA1: “Soil chemistry turned upside down: a
meta-analysis of invasive earthworm effects on soil chemical
properties”
MA2: “Earthworms affect plant growth and resistance
against herbivores: A meta-analysis”
MA3: “The unseen invaders:
introduced earthworms as drivers of change in plant communities in North
American forests (a meta-analysis)”
MA4: “Earthworms increase plant
production: a meta-analysis”
# DataFrame pour comparer les
fréquences des 4 MA:
library(tidyr)
frequency1 <- bind_rows(mutate(unnested_tokens1, author = "MA1"),
mutate(unnested_tokens2, author = "MA2"),
mutate(unnested_tokens3, author = "MA3"),
mutate(unnested_tokens4, author = "MA4"))%>%
mutate(word = stringr::str_extract(word, "[a-z']+")) %>%
count(author, word) %>%
group_by(author) %>%
mutate(proportion = n / sum(n)) %>%
select(-n) %>%
pivot_wider(names_from = author, values_from = proportion) %>%
pivot_longer(cols=c('MA2','MA3','MA4'),
names_to = "author", values_to = "proportion")
frequency2 <- bind_rows(mutate(unnested_tokens1, author = "MA1"),
mutate(unnested_tokens2, author = "MA2"),
mutate(unnested_tokens3, author = "MA3"),
mutate(unnested_tokens4, author = "MA4"))%>%
mutate(word = stringr::str_extract(word, "[a-z']+")) %>%
count(author, word) %>%
group_by(author) %>%
mutate(proportion = n / sum(n)) %>%
select(-n) %>%
pivot_wider(names_from = author, values_from = proportion) %>%
pivot_longer(cols=c('MA1','MA3','MA4'),
names_to = "author", values_to = "proportion")
frequency3 <- bind_rows(mutate(unnested_tokens1, author = "MA1"),
mutate(unnested_tokens2, author = "MA2"),
mutate(unnested_tokens3, author = "MA3"),
mutate(unnested_tokens4, author = "MA4"))%>%
mutate(word = stringr::str_extract(word, "[a-z']+")) %>%
count(author, word) %>%
group_by(author) %>%
mutate(proportion = n / sum(n)) %>%
select(-n) %>%
pivot_wider(names_from = author, values_from = proportion) %>%
pivot_longer(cols=c('MA1','MA2','MA4'),
names_to = "author", values_to = "proportion")
library(scales)
# expect a warning about rows with missing values being removed
ggplot(frequency1, aes(x = proportion, y = `MA1`,
color = abs(`MA1` - proportion))) +
geom_abline(color = "gray40", lty = 2) +
geom_jitter(alpha = 0.1, size = 2.5, width = 0.3, height = 0.3) +
geom_text(aes(label = word), check_overlap = TRUE, vjust = 1.5) +
scale_x_log10(labels = percent_format()) +
scale_y_log10(labels = percent_format()) +
scale_color_gradient(limits = c(0, 0.001),
low = "darkslategray4", high = "gray75") +
facet_wrap(~author, ncol = 2) +
theme(legend.position="none") +
labs(y = "MA1", x = NULL)
Les mots proches de la ligne dans ces graphiques ont des fréquences similaires dans les deux ensembles de textes, soit, dans l’ordre croissant: “accelerated”, “affecting”,“based”, “dweling”, “day”, “change”, “common”, “availability”, “negative”, “abundance”, “content”, “increase”, “activity”, “concentration”, “litter”, “biomass”, “specie”, “soil”, “earthworm”. On remarque que les mots les plus fréquents semblent être plus directement liés au sujet de l’article que les autres, qui paraissent plus générique au vocabulaire scientifique en écologie.
Les mots “invasion”, “carbon”, “layer” et “loss” sont plus fréquents dans la MA1 que dans la MA2, tandis que les mots “plant”, “root”, “shoot” et “grass” sont plus fréquents dans la MA2 que de la MA1.
Les mots “specie”, “effect”, “soil” et “earthworm” représentent entre 1 et 10% des mots totaux de chaque métaanalyse pour les métaanalyses 1 et 2 (échelle logarithmique).
Les mots proches de la ligne dans ces graphiques ont des fréquences similaires dans les deux ensembles de textes, soit, dans l’ordre croissant: “assessed”, “basal”, “abundant”, “abiotic”, “day”, “biotic”, “avalability”, “compared”, “america”, “invasive”, “european”, “abundance”, “study”, “nutrient”, “increased”, “exotic”, “ecosystem”, “impact”, “litter”, “biomass”, “effect”, “invasion”, “forest”, “specie”, “soil”, “earthworm”. On remarque que certains mots dont la fréquence est proches pourraient peut-être faire partie du même groupe de mots (comme “invasive european”,“nutrient increased”, “ecosystem impact” ou encore “litter biomass”.)
Les mots “pool”, “carbon”, et “microbial sont plus fréquents dans la MA1 que dans la MA3, tandis que les mots “cover”, “tree”, “density” et “plant” sont plus fréquents dans la MA3 que de la MA1.
Les mots “specie”, “forest,”soil” et “earthworm” représentent entre 1 et 10% des mots totaux de chaque métaanalyse pour les métaanalyses 1 et 3 (échelle logarithmique). On peut remarquer une forte ressemblance avec les résultats obtenus entre les MA 1 et 2.
Les mots proches de la ligne dans ces graphiques ont des fréquences similaires dans les deux ensembles de textes, soit, dans l’ordre croissant: “access”,“acquisition”,“data”,“australia”, “amonium”, “applied”, “analysis”, “due”, “mass”, “direct”, “affect”, “system”, “native”, “ecosystem”, “density”, “experiment”, “organic”, “activity”, “litter”, “community”, “biomass”, “specie”, effect, earthworm. On remarque que certains mots dont la fréquence est proches pourraient peut-être faire partie du même groupe de mots (comme acquisition data, direct effect, native ecosystem, ou encore litter community).
Les mots “forest”,“invasion”, “carbon” et “floor” sont plus fréquents dans la MA1 que dans la MA4, tandis que les mots “invader”, “functional”, “grassland”, “grass” et “plant” sont plus fréquents dans la MA4 que de la MA1.
Les mots “effect” et “earthworm” représentent entre 1 et 10% des mots totaux de chaque métaanalyse pour les métaanalyses 1 et 4 (échelle logarithmique).
Dans cette configuration, la MA1 et la MA4 semblent être les plus similaires en termes de fréquences de mots (nuage de points davantage resserré autour de la droite.)
Dans cette configuration, la MA1 et la MA2 semblent être les moins similaires en termes de fréquences de mots (nuage de points davantage dispersé autour de la droite.)
Quel est le degré de corrélation entre les fréquences de mots de chaque métaanalyse ?
cor.test(data = frequency1[frequency1$author == "MA2",],
~ proportion + `MA1`)
##
## Pearson's product-moment correlation
##
## data: proportion and MA1
## t = 17.22, df = 362, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.6103556 0.7239044
## sample estimates:
## cor
## 0.6710462
cor.test(data = frequency1[frequency1$author == "MA3",],
~ proportion + `MA1`)
##
## Pearson's product-moment correlation
##
## data: proportion and MA1
## t = 26.491, df = 395, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.7614356 0.8327697
## sample estimates:
## cor
## 0.7999107
cor.test(data = frequency1[frequency1$author == "MA4",],
~ proportion + `MA1`)
##
## Pearson's product-moment correlation
##
## data: proportion and MA1
## t = 30.246, df = 591, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.7457166 0.8091686
## sample estimates:
## cor
## 0.7794336
cor.test(data = frequency2[frequency2$author == "MA3",],
~ proportion + `MA2`)
##
## Pearson's product-moment correlation
##
## data: proportion and MA2
## t = 19.668, df = 228, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.7397460 0.8367073
## sample estimates:
## cor
## 0.7932011
cor.test(data = frequency2[frequency2$author == "MA4",],
~ proportion + `MA2`)
##
## Pearson's product-moment correlation
##
## data: proportion and MA2
## t = 33.547, df = 529, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.7955062 0.8501921
## sample estimates:
## cor
## 0.824768
cor.test(data = frequency3[frequency3$author == "MA4",],
~ proportion + `MA3`)
##
## Pearson's product-moment correlation
##
## data: proportion and MA3
## t = 19.575, df = 316, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.6861759 0.7862586
## sample estimates:
## cor
## 0.7402917
| MA1 | MA2 | MA3 | MA4 | |
|---|---|---|---|---|
| MA1 | - | 0.671 | 0.799 | 0.779 |
| MA2 | - | 0.793 | 0.825 | |
| MA3 | - | 0.740 | ||
| MA4 | - |
MA1: “Soil chemistry turned upside down: a meta-analysis of
invasive earthworm effects on soil chemical properties”
MA2:
“Earthworms affect plant growth and resistance against herbivores: A
meta-analysis”
MA3: “The unseen invaders: introduced earthworms as
drivers of change in plant communities in North American forests (a
meta-analysis)”
MA4: “Earthworms increase plant production: a
meta-analysis”
D’après le tableau ci-dessus, on peut voir que le choix de mots est le plus corrélé (correlation de Pearson) entre la MA2 et la MA4 (r²=0.825), tandis que le choix de mots est le moins corrélé (corrélation de Pearson) entre la MA1 et la MA2 (r²=0.671).
On commence par construire des Tibbles contenant chaque mot exprimant un sentiment positif ou négatif (colonne word), puis on compte le nombre d’occurence de chaque mot (colonne n).
library(tidytext)
bing<-get_sentiments("bing")
senti1<-unnested_tokens1 %>%
inner_join(bing) %>%
count(word, sort = TRUE)
senti2<-unnested_tokens2 %>%
inner_join(bing) %>%
count(word, sort = TRUE)
senti3<-unnested_tokens3 %>%
inner_join(bing) %>%
count(word, sort = TRUE)
senti4<-unnested_tokens4 %>%
inner_join(bing) %>%
count(word, sort = TRUE)
On ne conserve que les dix premières valeurs et les dix dernières valeurs, afin de pouvoir produire des graphiques plus lisibles ne conservant que les valeurs extrêmes.
library(tidyr)
MA1_senti <- senti1 %>%
inner_join(get_sentiments("bing")) %>%
anti_join(custom_stop_words, by = c("word")) %>%
pivot_wider(names_from = sentiment, values_from = n, values_fill = 0) %>%
mutate(sentiment = positive - negative)
sub1_MA1_senti<-MA1_senti %>%
arrange(sentiment) %>%
slice(1:10)
sub2_MA1_senti<-MA1_senti %>%
arrange(desc(sentiment)) %>%
slice(1:10)
sub_MA1_senti<-bind_rows(sub1_MA1_senti, sub2_MA1_senti)
On réalise un premier barplot de sentiment à titre d’exemple, en associant à chaque mot positif l’indice +1, et à chaque mot négatif l’indice -1. On représente ensuite cela graphiquement chaque mot en abscisse et la somme de ses indices (dont la valeur dépend de sa connotation et du nombre d’occurences) en ordonnées. On peut noter que certains mots neutres dans un contexte scientifique (comme “plot” ou “manipulation”) ont été rajoutés au dictionaire de “stop words”, pour éviter qu’ils soient considérés à tort comme des mots à valence négative.
ggplot(sub_MA1_senti, aes(x = word, y = sentiment, fill = factor(sign(sentiment)))) +
geom_bar(stat = "identity") +
labs(x = "Word", y = "Sentiment Score", fill = "Sentiment") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
On répète le processus pour comparer les métaanalyses 1,2,3 et 4.
library(tidyr)
library(ggplot2)
plot_sentiment_subset <- function(senti) {
MA_senti <- senti %>%
inner_join(get_sentiments("bing")) %>%
pivot_wider(names_from = sentiment, values_from = n, values_fill = 0) %>%
mutate(sentiment = positive - negative)
sub1_MA_senti <- MA_senti %>%
anti_join(custom_stop_words, by = c("word")) %>%
arrange(sentiment) %>%
slice(1:5)
sub2_MA_senti <- MA_senti %>%
anti_join(custom_stop_words, by = c("word")) %>%
arrange(desc(sentiment)) %>%
slice(1:5)
sub_MA_senti <- bind_rows(sub1_MA_senti, sub2_MA_senti)
ggplot(sub_MA_senti, aes(x = word, y = sentiment, fill = factor(sign(sentiment)))) +
geom_bar(stat = "identity") +
labs(x = "Word", y = "Sentiment Score", fill = "Sentiment") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
}
plot_senti1<-plot_sentiment_subset(senti1)
plot_senti2<-plot_sentiment_subset(senti2)
plot_senti3<-plot_sentiment_subset(senti3)
plot_senti4<-plot_sentiment_subset(senti4)
library(egg)
ggarrange(plot_senti1,plot_senti2,plot_senti3,plot_senti4,widths = c(2,2),labels = c("1","2","3","4"))
Tout d’abord, il est immportant de noter que tous les graphes n’ont pas les mêmes échelles ; les MA1 et 4 semblent avoir des échelles de sentiment comparables ([-20;10] et [-10;20]) et cela vaut aussi pour les MA2 et 3 ([-10;5] et [-5;10])
On peut constater que le mot positif “abundance” est retrouvé dans la plupart de métaanalyses (1,2 et 3). Il serait cependant nécessaire d’inspecter des unités textuelles plus larges pour interpréter au mieux ce résultat, car la signification de ces mots peut grandement dépendre des autres mots auquels ils sont associés et du contexte. le mot “dynamic n’est retrouvé que dans les MA1 et 3. A l’inverse, Le mot “unaffected” n’est quant à lui retrouvé que dans les MA2 et 4. On peut émettre l’hypothèse que les MA2 et 4 se focalisent sur les mécanismes de préservation et de résistance, alors que la 1 et la 3 sont davantage axées sur la dynamique des écosystèmes.
On peut constater qu’il n’y a aucun mot négatif commun à tous les corpus. Cependant, les mots “invasive” ou “invader” sont retrouvées dans las MA 1, 3 et 4, ce qui sous-entend que la MA2 s’intéresse moins aux espèces invasives que les trois autres. On peut aussi remarquer que le mot “loss” n’est retrouvé que dans les MA1 et 4, ce qui semble indiquer que les effets négatifs relevés ne sont pas forcément liés à des pertes de caractéristiques. Le mot “severity”, à l’inverse, n’est retrouvé que dans les MA3 et 4, ce qui signifie peut-être qu’elles sont plus “quantitatives” que les deux autres. On peut enfin constater que le mot “loss” est le mot avec le score négatif le plus important des quatre graphiques, représenté dans la MA1.
MA1: “Soil chemistry turned upside down: a meta-analysis of
invasive earthworm effects on soil chemical properties”
MA2:
“Earthworms affect plant growth and resistance against herbivores: A
meta-analysis”
MA3: “The unseen invaders: introduced earthworms as
drivers of change in plant communities in North American forests (a
meta-analysis)”
MA4: “Earthworms increase plant production: a
meta-analysis”
bing_word_counts1 <- unnested_tokens1 %>%
inner_join(get_sentiments("bing")) %>%
count(word, sentiment, sort = TRUE) %>%
mutate(MA="MA1") %>%
ungroup()
bing_word_counts2 <- unnested_tokens2 %>%
inner_join(get_sentiments("bing")) %>%
count(word, sentiment, sort = TRUE) %>%
mutate(MA="MA2") %>%
ungroup()
bing_word_counts3 <- unnested_tokens3 %>%
inner_join(get_sentiments("bing")) %>%
count(word, sentiment, sort = TRUE) %>%
mutate(MA="MA3") %>%
ungroup()
bing_word_counts4 <- unnested_tokens4 %>%
inner_join(get_sentiments("bing")) %>%
count(word, sentiment, sort = TRUE) %>%
mutate(MA="MA4") %>%
ungroup()
contrib1<-bing_word_counts1 %>%
anti_join(custom_stop_words, by = c("word")) %>%
group_by(sentiment) %>%
slice_max(n, n = 10) %>%
ungroup() %>%
mutate(word = reorder(word, n)) %>%
ggplot(aes(n, word, fill = sentiment)) +
geom_col(show.legend = FALSE) +
facet_wrap(~sentiment, scales = "free_y") +
labs(x = "Contribution to sentiment",
y = NULL)
contrib2<-bing_word_counts2 %>%
anti_join(custom_stop_words, by = c("word")) %>%
group_by(sentiment) %>%
slice_max(n, n = 10) %>%
ungroup() %>%
mutate(word = reorder(word, n)) %>%
ggplot(aes(n, word, fill = sentiment)) +
geom_col(show.legend = FALSE) +
facet_wrap(~sentiment, scales = "free_y") +
labs(x = "Contribution to sentiment",
y = NULL)
contrib3<-bing_word_counts3 %>%
anti_join(custom_stop_words, by = c("word")) %>%
group_by(sentiment) %>%
slice_max(n, n = 10) %>%
ungroup() %>%
mutate(word = reorder(word, n)) %>%
ggplot(aes(n, word, fill = sentiment)) +
geom_col(show.legend = FALSE) +
facet_wrap(~sentiment, scales = "free_y") +
labs(x = "Contribution to sentiment",
y = NULL)
contrib4<-bing_word_counts4 %>%
anti_join(custom_stop_words, by = c("word")) %>%
group_by(sentiment) %>%
slice_max(n, n = 10) %>%
ungroup() %>%
mutate(word = reorder(word, n)) %>%
ggplot(aes(n, word, fill = sentiment)) +
geom_col(show.legend = FALSE) +
facet_wrap(~sentiment, scales = "free_y") +
labs(x = "Contribution to sentiment",
y = NULL)
library(egg)
ggarrange(contrib1,contrib2,contrib3,contrib4,widths = c(2,2),labels = c("1","2","3","4"))
Tout d’abord, il faut noter que les graphiques ne sont pas à la même échelle en abscisse. Cela ne pose en théorie pas de problème pour interpréter les résultats au cas par cas, mais cela rentrera en jeux lors d’éventuelles comparaisons entre métaanalyses.
Les quatre mots positifs les plus importants en contribution sont:
* MA1: “abundance”, dynamic”,
“dominated”,“positive”.
* MA2: “enhanced”, “abundance”,
“variety”,“unaffected”.
* MA3: “richness”, “abundance”,
“leading”, “dynamic”.
* MA4: “unnaffected”,
“enhanced”,“enhance”,“positive”.
Le mot “unaffected” compte parmi les 4 premiers dans les MA2
et 4 (qui semblent davantage s’intéresser aux plantes), là où le mot
“positive” compte parmi les quatre premiers pour les MA1 et 4,
qui semblent se focaliser sur les sols (d’après les titres). Cela
pourrait vouloir dire que, d’après ces métaanalyse, les vers de terre
ont un impact plutôt positif sur les sols et les plantes. Cependant,
l’approche en unités textuelles plus larges, comme les n-grames, semble
souhaitable pour éviter les contresens. Par ailleurs, le mot
“abundance” est dans les premiers pour les MA 1, 2 et 3, mais
pas pour la MA4, ce qui pourrait signifier qu’elle est moins orientée
sur la richesse écosystémique que les autres. De plus, la présence des
mots “enhanced” et “enhance” semble montrer que, comme
son nom l’indique, elle choisit une approche plus quantitative (étude de
la production) que les autres.
Les quatre mots négatifs les plus importants en contribution (en
ne comptant pas “rocky”, qui dans ce contexte est sans doute employé au
sens propre de “rocheux/rocailleux”, comme par exemple dans le groupe de
mots “Rocky area”.) sont:
* MA1: “loss”, “invasive”,
“negative”, “poorly”.
* MA2: “drought”, “negative”,
“dead”,“absence”.
* MA3: “invasive”, “burned”,
“severity”,“negative”.
* MA4: “invader”, “severity”,
“infested”,“absence”.
On remarque d’abord qu’aucun des mots négatifs
relevés n’est présent dans les quatre premiers de toutes les
métaanalyses. Cela dit, le mot “negative” semble être le mieux
réparti, car présent dans 3 MA sur les 4 (1,2 et 3). De la même façon,
on peut aussi noter que les mots “invasive” et
“invader” sont aussi présents dans les 4 premiers de 3 MA sur
les 4 (1,3 et 4, respectivement en 2e et 1er position pour
“invasive” et 1er position pour “invader”).
On
peut aussi noter que “invasive” semble souvent dans le même
groupe que “negative (MA1,3), tandis que le mot
“invader”, lui, semble plutôt associé avec “infested”
(MA4).
La MA2 semble sortir du lot, avec des mots uniques comme
“drought” et “dead”. Cela pourrait indiquer que
l’étude s’intéresse davantage aux effets des vers de terre sur la
physiologie végétale en tant que telle plutôt qu’à leurs aoports
écologiques ou de production, ce qui semble en accord avec le titre
donné à cette métaanalyse.
Da façon simpliste, il semble donc possible, à partir de ces
graphiques, de proposer une première catégorisation comme suit:
-
MA1/MA3: étude de l’impact écologique des vers de terre
sur les écosystèmes.
- MA2: étude des effets des
vers de terre sur la physiologie végétale.
- MA4:
étude de l’influence des vers de terre invasifs sur la production
végétale.
Cependant, il serait peut-être nécessaire d’étudier des unités textuelles plus larges, comme par exemple les phrases ou les n-grames, pour éviter au maximum le risque de contresens.
MA1: “Soil chemistry turned upside down: a meta-analysis of
invasive earthworm effects on soil chemical properties”
MA2:
“Earthworms affect plant growth and resistance against herbivores: A
meta-analysis”
MA3: “The unseen invaders: introduced earthworms as
drivers of change in plant communities in North American forests (a
meta-analysis)”
MA4: “Earthworms increase plant production: a
meta-analysis”
Visuellement, on peut voir sur le nuage de mots que les termes prépondérants dans la MA1 sont : “earthworm”,“soil”,“forest” et “effect”. On peut remarquer aussi que le mot “invasion” semble aussi relativement fréquent, ce qui est cohérent avec le titre de l’article (“invasive earthworms”). La prépondérance du mot “earthworm” sur les autres semble confirmer que les vers de terre sont le sujet principal de cette métaanalyse.
library(wordcloud)
library(dplyr)
unnested_tokens1 %>%
anti_join(stop_words) %>%
count(word) %>%
with(wordcloud(word, n, max.words = 50))
cloud1 <- recordPlot()
Visuellement, on peut voir sur le nuage de mots que les termes prépondérants dans la MA2 sont : “plant”,“earthworm”,“aphid”, “soil” et “effect”. D’autres mots tel que “increased”, “community”, “interaction”, “presence” ou “biomass” semblent décrire un processus biologique dynamique. La prépondérance de “plant” sur les autres semble confirmer que la biologie végétale en lien avec les vers de terre est le thème principal de cette métaanalyse.
unnested_tokens2 %>%
anti_join(stop_words) %>%
count(word) %>%
with(wordcloud(word, n, max.words = 50))
cloud2 <- recordPlot()
Visuellement, on peut voir sur le nuage de mots que les termes prépondérants dans la MA3 sont : “earthworm”,“specie”, “plant” et “forest”. La prépondérance des mots “earthworm” et “specie” sur les autres semble confirmer que la métaanlyse s’intéresse en particulier à la façon dont les différentes espèces de vers de terre (natives ou introduite) influent sur l’écosystème global (et notamment l’écosystème forestier). D’autres mots tel que “invasion”, “community”, “interaction”, “presence” ou “biomass” semblent décrire un processus écologique dynamique.
unnested_tokens3 %>%
anti_join(stop_words) %>%
count(word) %>%
with(wordcloud(word, n, max.words = 50))
cloud3 <- recordPlot()
Visuellement, on peut voir sur le nuage de mots que les termes prépondérants dans la MA4 sont : “earthworm”,“soil”, “plant” et “increased”. La prépondérance de ces mots semble confirmer que cette métaanalyse montre un effet positif (“increased” et “production”) des vers de terre sur les plantes, via, probablement, une amélioration de la qualité des sols (voir des mots comme “decomposer”, “nurient”, “growth”, “organic”, qui sont souvent utilisés pour décrire les sols favorables à la croissance végétale).
unnested_tokens4 %>%
anti_join(stop_words) %>%
count(word) %>%
with(wordcloud(word, n, max.words = 50))
cloud4 <- recordPlot()
Visuellement, on peut voir sur le nuage de mots que les termes positfs prépondérants dans la MA1 sont “abundance”, “dynamic” et dominated, tandis que les termes négatifs prépondérants sont “loss”,“invasive” et “negative”. On remarque tout d’abord que ces résultats sont très différents de ceux trouvés dans la partie précédente pour la même métaanalyse (Wordclouds: Wordcloud MA1) à cause de l’ajout de la variable “sentiment”. On peut aussi constater grâce à la taille de chaque mot du nuage et à la quantité de mots négatifs et positifs que la métaanalyse 1 semble porter un avis plutôt négatif sur son sujet d’étude (ici, l’impact des vers de terre sur les écosystèmes).
library(reshape2)
unnested_tokens1 %>%
anti_join(custom_stop_words, by = c("word")) %>%
inner_join(get_sentiments("bing")) %>%
count(word, sentiment, sort = TRUE) %>%
acast(word ~ sentiment, value.var = "n", fill = 0) %>%
comparison.cloud(colors = c("red", "blue"),
max.words = 100)
cloud_senti1<-recordPlot()
Visuellement, on peut voir sur le nuage de mots que les termes positfs prépondérants dans la MA2 sont “enhanced”, “abundance” et variety, tandis que les termes négatifs prépondérants sont “drought”,“negative” et “dead”. On remarque tout d’abord que ces résultats sont très différents de ceux trouvés dans la partie précédente pour la même métaanalyse (Wordclouds: Wordcloud MA2) à cause de l’ajout de la variable “sentiment”. On peut aussi constater grâce à la taille de chaque mot du nuage et à la quantité de mots négatifs et positifs que la métaanalyse 2 semble porter un jugement moins tranché que la précédente sur son sujet d’étude, sans dominance claire des mots positifs ou des mots négatifs (même si le mot le plus représenté, “drought”, est un mot à valence négative).
unnested_tokens2 %>%
anti_join(custom_stop_words, by = c("word")) %>%
inner_join(get_sentiments("bing")) %>%
count(word, sentiment, sort = TRUE) %>%
acast(word ~ sentiment, value.var = "n", fill = 0) %>%
comparison.cloud(colors = c("red", "blue"),
max.words = 100)
cloud_senti2<-recordPlot()
Visuellement, on peut voir sur le nuage de mots que les termes positfs prépondérants dans la MA3 sont “richness”, “abundance” et significant, tandis que les termes négatifs prépondérants sont “invasive”,“burned” et “negative”. On remarque tout d’abord que ces résultats sont très différents de ceux trouvés dans la partie précédente pour la même métaanalyse (Wordclouds: Wordcloud MA3) à cause de l’ajout de la variable “sentiment”. On peut aussi constater grâce à la taille de chaque mot du nuage et à la quantité de mots négatifs et positifs que la métaanalyse 3 semble aussi porter jugement nuancé sur son sujet d’étude, sans dominance claire des mots positifs ou des mots négatifs (même si le mot le plus représenté, “richness”, est un mot à valence positive). On peut cependant constater par la présence du mot “invasive” et du mot “invader” dans le même nuage que cette métaanalyse semble davantage parler d’invasion biologique que les autres.
unnested_tokens3 %>%
anti_join(custom_stop_words, by = c("word")) %>%
inner_join(get_sentiments("bing")) %>%
count(word, sentiment, sort = TRUE) %>%
acast(word ~ sentiment, value.var = "n", fill = 0) %>%
comparison.cloud(colors = c("red", "blue"),
max.words = 100)
cloud_senti3<-recordPlot()
Visuellement, on peut voir sur le nuage de mots que les termes positfs prépondérants dans la MA4 sont “significant”, “unaffected” et “enhance”, tandis que les termes négatifs prépondérants sont “invader”,“severity” et “infested”. On remarque tout d’abord que ces résultats sont très différents de ceux trouvés dans la partie précédente pour la même métaanalyse (Wordclouds: Wordcloud MA4) à cause de l’ajout de la variable “sentiment”. On peut cependant constater par la présence des mots “infested”, “severity”, “absence” et “invader” que la métaanalyse semble porter un jugement plutôt négatif, ce qui semble étonnant au vu du titre de la métaanalyse. Par ailleurs, même si le mot central, “significant”, est théoriquement le plus fréquent, on pourrait penser que la métaanalyse contient plus de mots positifs que de mots négatifs. Cependant, nous avons déjà vu que dans un contexte scientifique, la valence de ce mot dépend beaucoup du groue de mots auquel il est associé.
unnested_tokens4 %>%
anti_join(custom_stop_words, by = c("word")) %>%
inner_join(get_sentiments("bing")) %>%
count(word, sentiment, sort = TRUE) %>%
acast(word ~ sentiment, value.var = "n", fill = 0) %>%
comparison.cloud(colors = c("red", "blue"),
max.words = 100)
cloud_senti4<-recordPlot()
sentences1 <- tibble(text = abstracts1) %>%
unnest_tokens(sentence, text, token = "sentences")
sentences2 <- tibble(text = abstracts2) %>%
unnest_tokens(sentence, text, token = "sentences")
sentences3 <- tibble(text = abstracts3) %>%
unnest_tokens(sentence, text, token = "sentences")
sentences4 <- tibble(text = abstracts4) %>%
unnest_tokens(sentence, text, token = "sentences")
library(dplyr)
library(purrr)
library(kableExtra)
bingnegative <- get_sentiments("bing") %>%
filter(sentiment == "negative")
unnested_tokens1 <- unnested_tokens1 %>%
mutate(MA = "MA1")
unnested_tokens2 <- unnested_tokens2 %>%
mutate(MA = "MA2")
unnested_tokens3 <- unnested_tokens3 %>%
mutate(MA = "MA3")
unnested_tokens4 <- unnested_tokens4 %>%
mutate(MA = "MA4")
MA_labels <- c("MA1", "MA2", "MA3", "MA4")
word_counts_MA <- c(length(unnested_tokens1$word), length(unnested_tokens2$word), length(unnested_tokens3$word), length(unnested_tokens4$word))
word_count_tibble <- tibble(
MA = MA_labels,
words = word_counts_MA
)
all_ratios <- bind_rows(unnested_tokens1,unnested_tokens2,unnested_tokens3,unnested_tokens4)
joined_tibble <- inner_join(all_ratios, bingnegative, by = "word")
MA_titles <- c("Soil chemistry turned upside down: a meta-analysis [...]","Earthworms affect plant growth and resistance [...]","The unseen invaders: [...] in north American forests (a meta-analysis)","Earthworms increase plant production: a meta-analysis")
summary_tibble <- joined_tibble %>%
group_by(MA) %>%
summarize(
negativewords = n()
) %>%
left_join(word_count_tibble, by = "MA") %>%
mutate(ratio = negativewords / words) %>%
ungroup() %>%
mutate(MA_title = MA_titles) %>%
mutate(current_MA = MA) %>%
select(MA_title, current_MA, words, negativewords, ratio)
summary_tibble %>%
kbl() %>%
kable_material_dark("hover", full_width = F) %>%
row_spec(0, bold = T, color = "black", background = "#D7261E")
| MA_title | current_MA | words | negativewords | ratio |
|---|---|---|---|---|
| Soil chemistry turned upside down: a meta-analysis […] | MA1 | 5616 | 187 | 0.0332977 |
| Earthworms affect plant growth and resistance […] | MA2 | 2959 | 88 | 0.0297398 |
| The unseen invaders: […] in north American forests (a meta-analysis) | MA3 | 1860 | 49 | 0.0263441 |
| Earthworms increase plant production: a meta-analysis | MA4 | 4985 | 102 | 0.0204614 |
Ci-dessus un classement des métaanalyses contenant le plus de
mots négatifs (MA1>MA2>MA3>MA4), normalisés en fonction du
nombre de mots dans chaque métaanalyse (colonne “ratio”). On peut
remarquer que les métaanalyses sont exactement en ordre décroissant (la
MA1 est la plus négative, la MA4 la moins négative), ce qui est une
coïncidence plutôt surprenante. On peut donc écrire, de manière
synthétique, que:
* MA1: 3,3% des mots totaux sont
des mots négatifs.
* MA2: 2,9% des mots totaux sont
des mots négatifs.
* MA3: 2,6% des mots totaux sont
des mots négatifs.
* MA4: 2% des mots totaux sont
des mots négatifs.
Ces ratios permettent notamment d’expliquer par
des proportions précises la différence observée plus tôt entre les
nuages de mots bruts et les nuages de mots prenant en compte la valence
(score de sentiment) des mots, les deux groupes étudiés étant de taille
et de composition tès différente.
Définitions:
tf: term
frequency.
idf: inverse document frequency. Plus élaboré
que l’approche en “stop words”. Diminue la fréquence des termes
rencontrés très souvent et augmente la fréquence des termes rares, en
jouant sur la pondération.
tf-idf: le produit de ces deux
indices. Il premet d’identifier les mots qui sont plus
importants pour un document spécifique parmi un ensemble de
documents.
unnested_tokens1 <- tibble(abstracts1) %>%
mutate(MA="MA1") %>%
unnest_tokens(word, abstracts1)
unnested_tokens1<-unnested_tokens1 %>% rowwise() %>% mutate(word = singularize(word))
unnested_tokens2 <- tibble(abstracts2) %>%
mutate(MA="MA2") %>%
unnest_tokens(word, abstracts2)
unnested_tokens2 <- unnested_tokens2 %>% rowwise() %>% mutate(word = singularize(word))
unnested_tokens3 <- tibble(abstracts3) %>%
mutate(MA="MA3") %>%
unnest_tokens(word, abstracts3)
unnested_tokens3 <- unnested_tokens3 %>% rowwise() %>% mutate(word = singularize(word))
unnested_tokens4 <- tibble(abstracts4) %>%
mutate(MA="MA4") %>%
unnest_tokens(word, abstracts4)
unnested_tokens4 <- unnested_tokens4 %>% rowwise() %>% mutate(word = singularize(word))
word_counts_MA <- c(length(unnested_tokens1$word), length(unnested_tokens2$word), length(unnested_tokens3$word),length(unnested_tokens4$word))
ordre1=unnested_tokens1 %>%
count(word, sort = TRUE) %>%
mutate(word = reorder(word, n,decreasing=TRUE))
tokens_ordered_1 <- left_join(unnested_tokens1, ordre1) %>%
mutate(Total=word_count_tibble$words[1])
ordre2=unnested_tokens2 %>%
count(word, sort = TRUE) %>%
mutate(word = reorder(word, n,decreasing=TRUE))
tokens_ordered_2 <- left_join(unnested_tokens2, ordre2) %>%
mutate(Total=word_count_tibble$words[2])
ordre3=unnested_tokens4 %>%
count(word, sort = TRUE) %>%
mutate(word = reorder(word, n,decreasing=TRUE))
tokens_ordered_3 <- inner_join(unnested_tokens3, ordre3) %>%
mutate(Total=word_count_tibble$words[3])
ordre4=unnested_tokens4 %>%
count(word, sort = TRUE) %>%
mutate(word = reorder(word, n,decreasing=TRUE))
tokens_ordered_4 <- left_join(unnested_tokens4, ordre4) %>%
mutate(Total=word_count_tibble$words[4])
all_freq <- bind_rows(tokens_ordered_1,tokens_ordered_2,tokens_ordered_3,tokens_ordered_4) %>% mutate(word_frequency = n/Total)
library(ggplot2)
library(egg)
word_freq_plot1 <- ggplot(all_freq, aes(x = word_frequency, fill = MA)) +
geom_histogram(bins=100,show.legend = FALSE) +
ggtitle("xlim = max_word_frequency") +
theme(plot.title = element_text(hjust = 0.5)) +
xlim(NA, max(all_freq$word_frequency)) +
facet_wrap(~MA, ncol = 2, scales = "free_y")
word_freq_plot2 <-ggplot(all_freq, aes(x = word_frequency, fill = MA)) +
geom_histogram(bins=100,show.legend = FALSE) +
ggtitle("xlim = 0.05") +
theme(plot.title = element_text(hjust = 0.5)) +
xlim(NA, 0.05) +
facet_wrap(~MA, ncol = 2, scales = "free_y")
ggarrange(word_freq_plot1,word_freq_plot2,widths = c(1,2))
Ces graphiques présentent des distributions proches pour toutes les MA, avec de nombreux mots qui apparaissent rarement et moins de mots qui apparaissent fréquemment (le premier groupe de 4 graphes représentant l’intégralité des données, le deuxième groupe de 4 se focalisant uniquement sur l’intervalle [0;0.05], pour inspecter le massif de pics davantage en détail). En x, on peut voir que les mots apparaissant très souvent (à droite) sont rares, alors que les mots qui apparaissent peu souvent (à gauche) sont fréquents. Ces graphiques présentent des distributions similaires pour toutes les MA, avec de nombreux mots qui apparaissent rarement et moins de mots qui apparaissent fréquemment.
La loi de Zipf, découverte empiriquement par Zipf (1949) pour
des mots d’un corpus anglais, stipule que si f est la fréquence
d’un mot dans le corpus et r le rang, alors :
\(frequency \propto \frac{1}{rank}\)
(la
fréquence d’un mot donné est inversement proportionnelle à son
rang).
library(latex2exp)
freq_and_rank <- all_freq %>% group_by(MA) %>%
distinct(word, .keep_all = TRUE) %>%
arrange(desc(n)) %>%
mutate(rank = seq_len(length(word)), word_frequency = n/Total) %>% #
ungroup()
freq_and_rank %>%
ggplot(aes(rank, word_frequency, color = MA)) +
geom_line(linewidth = 1.1, alpha = 0.8, show.legend = TRUE) +
scale_x_log10() +
scale_y_log10() +
xlab(TeX("$\\log_{10}(Rank)$")) +
ylab(TeX("$\\log_{10}(Word~Frequency)$"))
Les courbes de Zipf (log10(f) contre log10(r)) obtenues ci-dessus
ont une pente négative. On peut visualiser graphiquement qu’il existe
bel et bien une relation inversement proportionnelle entre f et
r (échelle logarithmique). On peut cependant remarquer que la
décroissance observée n’est pas strictement monotone. On pourrait
considérer ces courbes comme des lois de puissance brisées (fonction par
morceaux donnée par une séquence de lois de puissance jointes où chaque
section a sa propre puissance (indice) et est définie par des “ruptures”
limitatives.) et les diviser en trois sections:
[1;10]/[10;100]/[100;1000]. Voyons quel est l’exposant de la loi de
puissance pour la partie centrale de la plage de rangs.
rank_subset <- freq_and_rank %>%
filter(rank < 100,
rank > 10)
lm(log10(word_frequency) ~ log10(rank), data = rank_subset)
##
## Call:
## lm(formula = log10(word_frequency) ~ log10(rank), data = rank_subset)
##
## Coefficients:
## (Intercept) log10(rank)
## -0.8048 -0.8272
library(latex2exp)
freq_and_rank %>% ggplot(aes(rank, word_frequency, color = MA)) +
geom_abline(intercept = -0.8048, slope = -0.8272,
color = "gray50", linetype = 2) +
geom_line(linewidth = 1.1, alpha = 0.8, show.legend = TRUE) +
scale_x_log10() +
scale_y_log10() +
xlab(TeX("$\\log_{10}(Rank)$")) +
ylab(TeX("$\\log_{10}(Word~Frequency)$"))
On peut remarquer en ragardant la partie supérieure que la MA3 contient
davantage de mots “rares” que la valeur prédite par le modèle linéaire,
alors que toutes les autres (courbes orange, vertes et blues) en
contiennent moins. La MA3 est donc celle qui contient la plus haute
fréquence de mots rares. Ce résultat semble logique lorsqu’on considère
que c’est aussi elle qui comprends le moins de mots totaux (MA3=1860
< MA2=2959 < MA4=4985 < MA1=5616, voir table
ci-dessous). Pour ce qui est des mots très fréquents (quart
inférieur droit sous 0.001 de fréquence), on peut constater que toutes
les métaanalyses en contiennent moins que la valeur prédite. Au centre,
les courbes des 4 MA sont relativement proche du modèle linéaire, ce qui
n’est pas particulièrement étonnant car il a justement été ajusté pour
convenir à l’intervalle correspondant à la partie centrale du
graphe.
word_count_tibble%>%
kbl() %>%
kable_material_dark("hover", full_width = F) %>%
row_spec(0, bold = T, color = "black", background = "#D7261E")
| MA | words |
|---|---|
| MA1 | 5616 |
| MA2 | 2959 |
| MA3 | 1860 |
| MA4 | 4985 |
MA_tf_idf <- all_freq %>%
distinct(word, .keep_all = TRUE) %>%
select(-word_frequency) %>%
select(-Total) %>%
bind_tf_idf(word, MA, n) %>%
arrange(desc(tf_idf))
MA_tf_idf
## # A tibble: 2,762 × 6
## # Rowwise:
## MA word n tf idf tf_idf
## <chr> <chr> <int> <dbl> <dbl> <dbl>
## 1 MA3 become 4 0.0833 1.39 0.116
## 2 MA3 tim 4 0.0833 1.39 0.116
## 3 MA3 k 4 0.0833 1.39 0.116
## 4 MA3 contribute 3 0.0625 1.39 0.0866
## 5 MA1 the 488 0.0494 1.39 0.0685
## 6 MA1 and 456 0.0462 1.39 0.0640
## 7 MA2 aphid 50 0.0456 1.39 0.0632
## 8 MA1 of 425 0.0430 1.39 0.0597
## 9 MA3 accumulation 2 0.0417 1.39 0.0578
## 10 MA3 april 2 0.0417 1.39 0.0578
## # ℹ 2,752 more rows
library(forcats)
MA_tf_idf %>%
anti_join(stop_words) %>%
anti_join(custom_stop_words) %>%
group_by(MA) %>%
slice_max(tf_idf, n = 15) %>%
ungroup() %>%
ggplot(aes(tf_idf, fct_reorder(word, tf_idf), fill = MA)) +
geom_col(show.legend = FALSE) +
facet_wrap(~MA, ncol = 2, scales = "free") +
labs(x = "tf-idf", y = NULL)
D’après les graphiques ci-dessus, on peut constater que:
- Les mots
“earthworm”, “soil”, “forest” et
“effect” sont plus souvent employés dans la MA1 que dans les
autres MA. Le mot “invasion” est aussi plus présent dans la MA1
que dans les autres MA.
- Les mots “aphid,
”nematode”, “organism” et “herbivore” sont
plus souvent employés dans la MA2 que dans les autres MA. Le mot
“parasitoid” est aussi plus présent dans la MA2 que dans les
autres MA.
- Les mots “tim” (forme de “times” après
‘singularize’?), “contribute”, “stage” et
“responsible” sont plus souvent employés dans la MA3 que dans
les autres MA.
Les mots “canopy” et “aggregate”
sont aussi plus présent dans la MA3 que dans les autres MA.
- Les
mots “maize, ”gtt”, “grain” et
“herbivore” sont plus souvent employés dans la MA4 que dans les
autres MA. Les mots du champs lexical de l’agriculture, comme
“harvest”, “fertilizer”, “farmer” et
“pb” (probablement employé ici comme le symbole chimique du
plomb) sont aussi plus présent dans la MA4 que dans les autres
MA.
Rappelons les suppositions faites précédemment dans la partie
“Analyse de sentiment”:
- MA1/MA3: étude de
l’impact écologique des vers de terre sur les écosystèmes.
-
MA2: étude des effets des vers de terre sur la
physiologie végétale.
- MA4: étude de l’influence
des vers de terre invasifs sur la production végétale.
En prenant en compte le sujet apparent de chaque métaanalyse, on peut
supposer que:
- La MA1 se focalise plus que les autres sur
l’impact écologique des vers de terre sur les forêts, sous la modalité
d’une “invasion” biologique.
- La MA2 se
focalise plus que les autres sur les organismes herbivores comme les
pucerons (“aphids”). Le mot “parasitoid” laisse
entendre un effet parasitaire des pucerons sur les végétaux. Cela semble
cohérent avec les résultats obtenus précédemment (voir “Analyse de
sentiment” et “Wordcloud: coloration en fonction de la valence des
mots”). D’après le titre de la métaanalyse, les vers de terre semblent
par contre avoir une influence positive sur la résistance des plantes
aux pucerons (id.).
- La MA3 se focalise plus que les autres
sur les effets des vers de terre sur les forêts (d’après le titre et le
mot-clé “canopy”), et sur les aggrégats, peut-être chimiques ou
biochimiques, présents dans le sol.
- La MA4 se focalise plus
que les autres sur les effets des vers de terre sur la production
végétale (comme semble l’indiquer le mot PLFA (acides gras
phospholipidiques), un marqueur de la biomasse vivante), d’après le
titre de la métaanalyse et le champs lexical abondant en lien avec le
monde agricole (“maize”, “grain”,
“herbivore”,“harvest”, “fertilizer”,
“farmer” et “pb”). Le terme “Pb”
semble indiquer que la métanalyse s’intéresse probablement aux
conséquences écosystémiques des métaux lourds présents dans le sol.
MA1: “Soil chemistry turned upside down: a meta-analysis of
invasive earthworm effects on soil chemical properties”
MA2:
“Earthworms affect plant growth and resistance against herbivores: A
meta-analysis”
MA3: “The unseen invaders: introduced earthworms as
drivers of change in plant communities in North American forests (a
meta-analysis)”
MA4: “Earthworms increase plant production: a
meta-analysis”
library(dplyr)
library(tidytext)
all_abstracts_df <- rbind(data.frame(abstract = abstracts1, MA = "MA1"),
data.frame(abstract = abstracts2, MA = "MA2"),
data.frame(abstract = abstracts3, MA = "MA3"),
data.frame(abstract = abstracts4, MA = "MA4"))
tokens_bigrams_all <- tibble(all_abstracts_df) %>%
unnest_tokens(bigram, abstract, token = "ngrams", n = 2) %>%
filter(!is.na(bigram))
tokens_bigrams1 <- tibble(abstracts1) %>%
unnest_tokens(bigram, abstracts1, token = "ngrams", n = 2) %>%
filter(!is.na(bigram))
tokens_bigrams2 <- tibble(abstracts2) %>%
unnest_tokens(bigram, abstracts2, token = "ngrams", n = 2) %>%
filter(!is.na(bigram))
tokens_bigrams3 <- tibble(abstracts3) %>%
unnest_tokens(bigram, abstracts3, token = "ngrams", n = 2) %>%
filter(!is.na(bigram))
tokens_bigrams4 <- tibble(abstracts4) %>%
unnest_tokens(bigram, abstracts4, token = "ngrams", n = 2) %>%
filter(!is.na(bigram))
tokens_bigrams1 %>% count(bigram, sort = TRUE)
## # A tibble: 6,279 × 2
## bigram n
## <chr> <int>
## 1 in the 81
## 2 of the 73
## 3 effects of 31
## 4 microbial biomass 31
## 5 organic matter 29
## 6 of earthworm 26
## 7 of earthworms 26
## 8 earthworm invasion 25
## 9 forest floor 25
## 10 c and 24
## # ℹ 6,269 more rows
tokens_bigrams2 %>%
count(bigram, sort = TRUE)
## # A tibble: 3,564 × 2
## bigram n
## <chr> <int>
## 1 in the 35
## 2 of earthworms 34
## 3 effects of 31
## 4 presence of 31
## 5 the presence 30
## 6 of the 28
## 7 on the 18
## 8 plant species 17
## 9 plant growth 16
## 10 affected by 15
## # ℹ 3,554 more rows
tokens_bigrams3 %>%
count(bigram, sort = TRUE)
## # A tibble: 2,448 × 2
## bigram n
## <chr> <int>
## 1 of the 19
## 2 in the 16
## 3 non native 15
## 4 plant species 15
## 5 native plant 14
## 6 earthworm species 11
## 7 of earthworm 11
## 8 and the 10
## 9 o tyrtaeum 10
## 10 changes in 9
## # ℹ 2,438 more rows
tokens_bigrams4 %>%
count(bigram, sort = TRUE)
## # A tibble: 6,044 × 2
## bigram n
## <chr> <int>
## 1 in the 80
## 2 of the 64
## 3 presence of 43
## 4 the presence 41
## 5 of earthworms 34
## 6 on the 28
## 7 the soil 27
## 8 plant community 26
## 9 effects of 25
## 10 in a 23
## # ℹ 6,034 more rows
De nombreux bigrammes sont non-informatifs (“in the”, “of the” etc.). On va donc réemployer l’approche en “stop words” des étapes précédentes pour enlever ces mots.
# bigrams ok, separated ok, filtered ok.
bigrams_separated_all <- tokens_bigrams_all %>%
separate(bigram, c("word1", "word2"), sep = " ")
bigrams_separated1 <- tokens_bigrams1 %>%
separate(bigram, c("word1", "word2"), sep = " ")
bigrams_filtered_all <- bigrams_separated_all %>%
filter(!word1 %in% combined_stop_words$word) %>%
filter(!word2 %in% combined_stop_words$word)
bigrams_filtered1 <- bigrams_separated1 %>%
filter(!word1 %in% combined_stop_words$word) %>%
filter(!word2 %in% combined_stop_words$word)
# new bigram counts:
bigram_counts_all <- bigrams_filtered_all %>%
count(MA, word1, word2, sort = TRUE)
bigram_counts1 <- bigrams_filtered1 %>%
count(word1, word2, sort = TRUE)
# For bigrams_2
bigrams_separated2 <- tokens_bigrams2 %>%
separate(bigram, c("word1", "word2"), sep = " ")
bigrams_filtered2 <- bigrams_separated2 %>%
filter(!word1 %in% combined_stop_words$word) %>%
filter(!word2 %in% combined_stop_words$word)
bigram_counts2 <- bigrams_filtered2 %>%
count(word1, word2, sort = TRUE)
# For bigrams_3
bigrams_separated3 <- tokens_bigrams3 %>%
separate(bigram, c("word1", "word2"), sep = " ")
bigrams_filtered3 <- bigrams_separated3 %>%
filter(!word1 %in% combined_stop_words$word) %>%
filter(!word2 %in% combined_stop_words$word)
bigram_counts3 <- bigrams_filtered3 %>%
count(word1, word2, sort = TRUE)
# For bigrams_4
bigrams_separated4 <- tokens_bigrams4 %>%
separate(bigram, c("word1", "word2"), sep = " ")
bigrams_filtered4 <- bigrams_separated4 %>%
filter(!word1 %in% combined_stop_words$word) %>%
filter(!word2 %in% combined_stop_words$word)
bigram_counts4 <- bigrams_filtered4 %>%
count(word1, word2, sort = TRUE)
bigrams_united_all <- bigrams_filtered_all %>%
unite(bigram, word1, word2, sep = " ")
bigrams_united_all %>% count(MA, bigram, sort = TRUE)
## # A tibble: 5,515 × 3
## MA bigram n
## <chr> <chr> <int>
## 1 MA1 microbial biomass 31
## 2 MA1 organic matter 29
## 3 MA4 plant community 26
## 4 MA1 earthworm invasion 25
## 5 MA1 forest floor 25
## 6 MA1 exotic earthworms 24
## 7 MA1 mineral soil 23
## 8 MA1 earthworm species 18
## 9 MA2 plant species 17
## 10 MA4 plant growth 17
## # ℹ 5,505 more rows
earthworms_bigrams <- bigrams_united_all %>%
filter(grepl("earthworms?", bigram, ignore.case = TRUE))
# Count occurrences of MA and word2 combination, sorted in descending order
count_earthworm_bigrams<- earthworms_bigrams %>%
count(MA, bigram, sort = TRUE) %>%
group_by(MA) %>%
filter(n>5) %>%
mutate(MA = factor(MA, levels = c("MA1", "MA2", "MA3", "MA4"))) %>% # Set the order of MA
arrange(MA, desc(n)) # Sort by MA and then by n in descending order
count_earthworm_bigrams
## # A tibble: 22 × 3
## # Groups: MA [4]
## MA bigram n
## <fct> <chr> <int>
## 1 MA1 earthworm invasion 25
## 2 MA1 exotic earthworms 24
## 3 MA1 earthworm species 18
## 4 MA1 earthworm activity 9
## 5 MA1 earthworm biomass 8
## 6 MA1 earthworm invaded 7
## 7 MA1 european earthworms 7
## 8 MA1 exotic earthworm 7
## 9 MA1 earthworm community 6
## 10 MA2 earthworms increased 7
## # ℹ 12 more rows
library(dplyr)
# Define the function
count_filtered_bigrams <- function(data, regex_motif,treshold) {
# Filter the bigrams based on the provided regex motif
filtered_bigrams <- data %>%
filter(grepl(regex_motif, bigram, ignore.case = TRUE))
# Count occurrences of each combination of `MA` and `bigram`, sort in descending order,
# group by `MA`, and filter counts greater than 5 within each group
count_bigrams <- filtered_bigrams %>%
count(MA, bigram, sort = TRUE) %>%
group_by(MA) %>%
filter(n > treshold) %>%
mutate(MA = factor(MA, levels = c("MA1", "MA2", "MA3", "MA4"))) %>%
arrange(MA, desc(n)) # Sort by MA and then by n in descending order
return(count_bigrams)
}
count_filtered_bigrams(bigrams_united_all,"earthworms?",5)
## # A tibble: 22 × 3
## # Groups: MA [4]
## MA bigram n
## <fct> <chr> <int>
## 1 MA1 earthworm invasion 25
## 2 MA1 exotic earthworms 24
## 3 MA1 earthworm species 18
## 4 MA1 earthworm activity 9
## 5 MA1 earthworm biomass 8
## 6 MA1 earthworm invaded 7
## 7 MA1 european earthworms 7
## 8 MA1 exotic earthworm 7
## 9 MA1 earthworm community 6
## 10 MA2 earthworms increased 7
## # ℹ 12 more rows
count_filtered_bigrams(bigrams_united_all,"invasions?",5)
## # A tibble: 3 × 3
## # Groups: MA [2]
## MA bigram n
## <fct> <chr> <int>
## 1 MA1 earthworm invasion 25
## 2 MA3 earthworm invasion 7
## 3 MA3 earthworm invasions 6
count_filtered_bigrams(bigrams_united_all,"invaders?",0)
## # A tibble: 9 × 3
## # Groups: MA [2]
## MA bigram n
## <fct> <chr> <int>
## 1 MA1 earthworm invaders 1
## 2 MA1 invaders affect 1
## 3 MA4 invader plants 2
## 4 MA4 invader species 2
## 5 MA4 plant invader 2
## 6 MA4 invader biomass 1
## 7 MA4 invader seed 1
## 8 MA4 invader treatments 1
## 9 MA4 plant invaders 1
count_filtered_bigrams(bigrams_united_all,"europeans?",0)
## # A tibble: 23 × 3
## # Groups: MA [4]
## MA bigram n
## <fct> <chr> <int>
## 1 MA1 european earthworms 7
## 2 MA1 european species 5
## 3 MA1 european earthworm 4
## 4 MA1 european settlers 2
## 5 MA1 introduced european 2
## 6 MA1 invasive european 2
## 7 MA1 european lumbricids 1
## 8 MA1 exotic european 1
## 9 MA1 processes european 1
## 10 MA1 time european 1
## # ℹ 13 more rows
bigram_tf_idf <- bigrams_united_all %>%
count(MA, bigram) %>%
bind_tf_idf(bigram, MA, n) %>%
arrange(desc(tf_idf))
bigram_tf_idf %>%
group_by(MA) %>%
slice_max(tf_idf, n = 15) %>%
ungroup() %>%
ggplot(aes(tf_idf, fct_reorder(bigram, tf_idf), fill = MA)) +
geom_col(show.legend = FALSE) +
facet_wrap(~MA, ncol = 2, scales = "free") +
labs(x = "tf-idf", y = NULL)
D’après les graphiques ci-dessus, on peut constater que:
Les
bigrammes “mineral soil”, “earthworm invasion”,
“exotic earthworms” et “forest soils” sont plus
souvent employés dans la MA1 que dans les autres MA. Le bigramme
“earthworm invaded” est aussi plus présent dans la MA1 que dans
les autres MA.
Les bigrammes “soil organisms”, “plant
responses”, “plant mediated” et “root herbivore”
sont plus souvent employés dans la MA2 que dans les autres MA. Le
bigramme “aphid species” est aussi plus présent dans la MA2 que
dans les autres MA.
Les bigrammes “tree species”,
“native plant”, “species richness” et “caterpillar
density” sont plus souvent employés dans la MA3 que dans les autres
MA. Le bigramme “earthworm invasions” est aussi plus présent
dans la MA3 que dans les autres MA.
Les bigrammes “soil
organisms”, “plant functionnal”, “dry weight” et
“diplocardia spp” sont plus souvent employés dans la MA4 que
dans les autres MA. Le bigramme “soil fertility” est aussi plus
présent dans la MA4 que dans les autres MA.
Rappelons les suppositions faites dans la section précédente:
-
La MA1 se focalise plus que les autres sur l’impact écologique
des vers de terre sur les forêts, sous la modalité d’une
“invasion” biologique.
- La MA2 se focalise
plus que les autres sur les organismes herbivores comme les pucerons
(“aphids”). Le mot “parasitoid” laisse entendre un
effet parasitaire des pucerons sur les végétaux. Cela semble cohérent
avec les résultats obtenus précédemment (voir “Analyse de sentiment” et
“Wordcloud: coloration en fonction de la valence des mots”). D’après le
titre de la métaanalyse, les vers de terre semblent par contre avoir une
influence positive sur la résistance des plantes aux pucerons (id.).
- La MA3 se focalise plus que les autres sur les effets des vers
de terre sur les forêts (d’après le titre et le mot-clé
“canopy”), et sur les aggrégats, peut-être chimiques ou
biochimiques, présents dans le sol.
- La MA4 se focalise plus
que les autres sur les effets des vers de terre sur la production
végétale (comme semble l’indiquer le mot PLFA (acides gras
phospholipidiques), un marqueur de la biomasse vivante), d’après le
titre de la métaanalyse et le champs lexical abondant en lien avec le
monde agricole (“maize”, “grain”,
“herbivore”,“harvest”, “fertilizer”,
“farmer” et “pb”). Le terme “Pb”
semble indiquer que la métanalyse s’intéresse probablement aux
conséquences écosystémiques des métaux lourds présents dans le
sol.
En prenant en compte le sujet apparent de chaque métaanalyse, on peut
supposer que:
- La MA1 se focalise plus que les autres sur
l’impact écologique des vers de terre “exotiques” sur
l’écosystème du sol forestier, sous la modalité d’une
“invasion” biologique.
- La MA2 se focalise
plus que les autres sur l’effet des “organismes du
sol”, et plus précisément ceux affectant les
“racines”, sur les plantes, en observant notamment,
probablement, les stratégies d’adaptation des plante face à cette source
de stress biotique (“plant responses”). Les “espèces de
pucerons” semblent particulièrement ciblées comme étant la
source de ce stress.
- La MA3 se focalise plus que les autres
sur l’impact écologique (“species richness”, “caterpillar
density”,“tree species”,“native plants”) des vers de terre invasifs
(“earthworm invasions”) sur les forêts d’Amérique du nord. Le
champ lexical de la richesse spécifique et de la diversité, ainsi que le
wordlcoud de la partie “Wordcloud: coloration en fonction de la valence
des mots (bleu: Positif / rouge: Négatif)”, semble évoquer un
“déclin”, un “dommage”, une “destruction”. On
peut donc en conclure que dans cette MA, les vers de terre invasifs sont
dépeints comme des nuisibles majeurs contre l’écosystème natif nord
américain.
- La MA4 se focalise plus que les autres sur les
effets des vers de terre et des organismes du sol sur
la production (“dry weight”) et la physiologie
végétale (“plant functionnal”). Elle s’intéresse aussi à la
fertilité des sol, ce qui semble cohérent avec le champ
lexical agricole relevé plus tôt (“maize”, “grain”,
“herbivore”,“harvest”, “fertilizer”,
“farmer” et “pb”). Le terme “Pb”
semble indiquer que la métanalyse s’intéresse probablement aux
conséquences écosystémiques des métaux lourds présents dans le
sol.
MA1: “Soil chemistry turned upside down: a meta-analysis of
invasive earthworm effects on soil chemical properties”
MA2:
“Earthworms affect plant growth and resistance against herbivores: A
meta-analysis”
MA3: “The unseen invaders: introduced earthworms as
drivers of change in plant communities in North American forests (a
meta-analysis)”
MA4: “Earthworms increase plant production: a
meta-analysis”
library(ggplot2)
AFINN <-get_sentiments("afinn")
not_words <- bigrams_separated_all %>%
filter(word1 == "not") %>%
inner_join(AFINN, by = c(word2 = "word")) %>%
count(word2, value, sort = TRUE)
not_words %>%
mutate(contribution = n * value) %>%
arrange(desc(abs(contribution))) %>%
mutate(word2 = reorder(word2, contribution)) %>%
ggplot(aes(contribution, word2, fill = contribution > 0)) +
geom_col(show.legend = FALSE) +
labs(x = "Sentiment value * number of occurrences",
y = "Words preceded by \"not\"")
## Les bigrammes “not benefit” et “not increase” sont
les plus important facteur d’erreur d’identification, faisant paraître
le texte plus positif qu’il ne l’est réellement.
Le
bigramme “not affected” est le plus important facteur d’erreur
d’identification, faisant paraître le texte plus
négatif qu’il ne l’est réellement.
library(ggplot2)
AFINN <-get_sentiments("afinn")
bigrams_separated1 %>%
filter(word1 == "not") %>%
inner_join(AFINN, by = c(word2 = "word")) %>%
count(word2, value, sort = TRUE)
## # A tibble: 2 × 3
## word2 value n
## <chr> <dbl> <int>
## 1 benefit 2 1
## 2 increase 1 1
not_words_with_factor <- bigrams_separated_all %>%
filter(word1 == "not") %>%
inner_join(AFINN, by = c(word2 = "word")) %>%
count(MA, word2, value, sort = TRUE)
not_words_with_factor %>%
mutate(contribution = n * value) %>%
arrange(desc(abs(contribution))) %>%
mutate(word2 = reorder(word2, contribution)) %>%
ggplot(aes(contribution, word2, fill = contribution > 0)) +
geom_col(show.legend = FALSE) +
labs(x = "Sentiment value * number of occurrences",
y = "Words preceded by \"not\"") +
coord_fixed(ratio = 0.25)+
facet_wrap(facets = vars(MA), ncol = 1)
Lorsque l’on inspecte le jeu de données pour chacune des
MA avec la fonction R “facet_grid”, on remarque que
les mots ayant conduit au plus d’erreurs d’identification dans chaque MA
sont:
- MA1: “benefit” et “increase”
classés à tort en positif (comme le mot précédant était
“not”, “not benefit” et “not increase” ont une valance
négative), pas de négatif relevé.
- MA2: Pas de mot
positif relevé. “affected” classé à tort en
négatif (comme le mot précédent était “not”, “not
affected” a une valence positive).
- MA3:
Pas de mot positif relevé. “affected” classé à tort en
négatif (comme le mot précédent était “not”, “not
affected” a une valence positive). On remarque
cependant que l’effet observé est moindre comparé à la MA2.
-
MA4: “responsible” (donc, le bigramme “not
responsible”), est classé positif par le dictionnaire AFINN, mais ces
seuls deux mots ne suffisent pas à déterminer la valence (positive ou
négative), de l’expression. Elles traduisent au contraire une forme de
neutralité (quelque-chose qui est non responsable d’un
effet est à priori neutre). Une analyse plus détaillée du contexte
d’utilisation serait requise pour pouvoir décider. Dans AFINN
(dictionnaire), “prevent” est classé négatif (c’est pourquoi
“not prevent” a une valence positive), mais en écologie, “not prevent”
semble bel et bien négatif (il n’y a donc pas d’erreur
d’identification dans cas précis). Par contre, classé à tort en
négatif, on retrouve là-aussi “affected”, dans
ce cas précédé par “not”, et donc de valence plutôt
positive.
Cependant, d’autres mots négatifs (comme
“never” etc.) n’ont pas été pris en compte dans l’analyse
ci-dessus. La prochaine étape à donc pour but de prendre davantage de
mots de négation en considération dans l’analyse de sentiment.
negation_words <- c("ain't", "aren't", "can't", "couldn't", "didn't", "doesn't", "don't", "hasn't",
"isn't", "mightn't", "mustn't", "neither", "never", "no", "nobody", "nor",
"not", "shan't", "shouldn't", "wasn't", "weren't", "won't", "wouldn't","without")
bigrams_separated_all %>%
filter(word1 %in% negation_words) %>%
inner_join(AFINN, by = c(word2 = "word"))
## # A tibble: 28 × 4
## MA word1 word2 value
## <chr> <chr> <chr> <dbl>
## 1 MA1 no significant 1
## 2 MA1 no significant 1
## 3 MA1 not increase 1
## 4 MA1 no greater 3
## 5 MA1 not benefit 2
## 6 MA1 no significant 1
## 7 MA1 no significant 1
## 8 MA1 neither affected -1
## 9 MA1 no significant 1
## 10 MA2 not affected -1
## # ℹ 18 more rows
library(dplyr)
library(ggplot2)
library(tidyr)
negation_words_with_factor <- bigrams_separated_all %>%
filter(word1 %in% negation_words) %>%
inner_join(AFINN, by = c(word2 = "word")) %>%
count(MA, word1, word2, value, sort = TRUE)
negation_words_with_factor %>%
mutate(contribution = n * value) %>%
arrange(desc(abs(contribution))) %>%
mutate(word2 = reorder(word2, contribution)) %>%
ggplot(aes(contribution, word2, fill = contribution > 0)) +
geom_col(show.legend = FALSE) +
labs(x = "Sentiment value * number of occurrences",
y = "Words preceded by negation word") +
coord_fixed(ratio = 0.25)+
facet_wrap(facets = vars(word1), ncol = 2)
Le fig.height agrandit l’espace blanc nul mais pas la figure. What
the fuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuck, comme dirait le Big
E.